
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections;
using System.Diagnostics;
using System.Globalization;
using Swaf;
using Swaf.BizObj;
using Swaf.BizRule;
using Swaf.Call;
using Swaf.Config;
using Swaf.Container;
using Swaf.Gui;
using Swaf.Logging;
using Swaf.Resource;
using Swaf.Security;

namespace Swaf
{
	/// <summary>
	/// The light-weight pure C# implementation of only the <c>IApplication</c> interface
	/// that is only needed in a multi-user hosting environment such as <i>ASP</i> or <i>ASP.NET</i>.
	/// </summary>
	/// <remarks>
	/// Instances of this class are associated one-to-one with "user sessions" in multi-user
	/// hosting environments.  Framework code that use <i>IApplication</i> should expect
	/// to be able to use this to work in within the context of a specific user of the
	/// application.
	/// <p>
	/// Instances of this class are obtained by calling the <c>Application.createSessionApp</c>
	/// method on the main application level <c>Application</c> object.</p></remarks>
	public class SessionApp : MarshalByRefObject, IApplication
	{
		private Application m_mainApp;
		private IMap m_sessionData;
		private IRuleManager m_ruleMgr;
		private string m_sessionId="";
		private ISecurityManager m_securityManager = null;
		private CultureInfo m_currentCulture;
		private ICall m_sessionValidator=null;
		private bool m_isRemoteGlobalApp=false;

        protected internal SessionApp(Application mainApp, string sessionId)
            :this(mainApp, sessionId, null)
        {
            //Intentionally left blank
        }
		protected internal SessionApp(Application mainApp, string sessionId, IDictionary startingData)
		{
			m_mainApp = mainApp;
			//m_sessionData = new FlexiMap();
			m_sessionData = (IMap) factories[@"Dictionaries"].createFromNickName(@"sessiondata");
            if (startingData != null)
                foreach (DictionaryEntry de in startingData)
                    m_sessionData[de.Key] = de.Value;

			m_ruleMgr = new RuleManager(this);
			m_sessionId=sessionId;
			m_securityManager = new SessionSecurityManager();
			m_sessionValidator=mainApp.SessionValidator;
			m_currentCulture=CultureInfo.CurrentCulture;

		}
		public string sessionId{get{return m_sessionId;}}

		public IAudit Audit {get{return m_mainApp.Audit;}}
		public ITrace Trace {get{return m_mainApp.Trace;}}
		public ILog Log {get{return m_mainApp.Log;}}

		public IRuleManager ruleMgr {get{return m_ruleMgr;}}

		public IMap appData {get{return m_mainApp.appData;}}

		public IResourceManager resMgr {get{return m_mainApp.resMgr;}}

		public IGuiManager guiMgr {get{return m_mainApp.guiMgr;}}

		public IMap sessionData {get{return m_sessionData;}}

		public IBizObjManager bizObjMgr {get{return m_mainApp.bizObjMgr;}}

		public IDictionary factory{get{return m_mainApp.factory;}}

		public IFactoryManager factories{get{return m_mainApp.factories;}}
		public ISecurityManager securityMgr{get{return m_securityManager;}}

		public bool inBrowseMode{get{return m_mainApp.inBrowseMode;}}
			/// <summary>
			/// Gets/Sets the currently configured culture for this application instance
			/// </summary>
			public virtual CultureInfo culture
		{
			get{return m_currentCulture;}
			set{m_currentCulture=value;}
		}
		/// <summary>
		/// Sets the current culture for this application instance by name.
		/// </summary>
		/// <param name="name"></param>
		public virtual void setCurrentCulture(string name)
		{
			culture=CultureInfo.CreateSpecificCulture(name);
		}

		public bool isValidSession
		{
			get
			{
				if (m_sessionValidator != null)
				{
					return (bool) m_sessionValidator.call(this.sessionId);
				}
				else
				{
					return true;
				}
			}
		}
		public ISessionInfo sessionInfo
		{
			get
			{
				// We need to capture the currentPrincipal.  Because the isValidSession property call
				// can call a custom sessionValidator which has the ability to change the 
				// principal that is set we need to be able to detect this.
				// Since the parameters are resolved left to right in the constructor call, the
				// securityMgr.currentPrincipal may be of a different value when it gets resolved than
				// it was before isValidSession is called
				object secPrin = securityMgr.currentPrincipal;
				
				return new SessionInfo(isValidSession, this.sessionId, 
					securityMgr.currentPrincipal.userName,securityMgr.currentPrincipal.instanceId, 
					securityMgr.currentPrincipal.additionalInfo, !Object.ReferenceEquals(secPrin, securityMgr.currentPrincipal));
			}
		}
		public bool isTiedToRemoteGlobalApp
		{
			get
			{
				return m_isRemoteGlobalApp;
			}
			set
			{
				m_isRemoteGlobalApp=value;
			}
		}

	}
}